package ConcurrentProgramming;



import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 *
 */
public class ExecutorDemo {
    public static void main(String[] args) {
        demo04();
    }

    /**
     * Executors.newCachedThreadPo0l  可回收缓存线程池
     *
     */
    public static void demo01() {
        ExecutorService executorService = Executors.newCachedThreadPool();
        for (int i = 0; i < 5; i ++) {
            executorService.execute(new demoLifoOff());
        }
        executorService.shutdown();
    }

    /**
     * Executors.newFixedThreadPool(10)
     * 如果达到最大数量会进行等待，知道有一个线程执行完毕之后交换给线程池
     */
    public static void demo02() {
        ExecutorService executorService = Executors.newFixedThreadPool(3); // 不同之处在于我们限制了线程数量
        for (int i = 0; i < 5; i++) {
            executorService.execute(new demoLifoOff());
        }
        executorService.shutdown();
    }

    /**
     * Executors.newSingleThreadExecutor()等价于 Executors.newFixedThreadPool(1)
     * 该线程池中的所有线程都是串行执行的
     *
     * 这个线程池只会创建单一线程。如果正在执行任务，并且有新的任务提交了，新的任务会被塞到一个LinkedBlockingQueue队列里，队列容量是int的最大值
     *
     * 如果关闭线程池之后右创建了新的可执行线程会抛出异常Exception in thread "main" java.util.concurrent.RejectedExecutionException
     * 表示无法接受任务时抛出此异常
     * 注意此时并不会直接退出，由下面的代码也看出虽然在执行的过程中抛出此异常，但是已经提交的线程还是执行完成了
     */
    public static void demo03() {
        // 单线程
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        executorService.execute(new demoLifoOff()); // 由于程序中设置了一个异常，但是整个程序并没有中断而是接着下一行代码执行一个新的线程
        // executorService.execute(new demoLifoOff()); // 串行执行
        // executorService.shutdownNow(); //如果不添加这一行代码，会阻塞，该方法的作用就是结束线程池，并不会直接执行，会等到以提交的线程执行完毕
        // executorService.shutdown(); //如果不添加这一行代码，会阻塞，该方法的作用就是结束线程池
        executorService.execute(new demoLifoOff()); // 在关闭线程池之后又开启一个新的线程
    }

    /**
     * 详细讨论可回收缓存线程池
     */
    public static void demo04() {
        ExecutorService executorService = Executors.newCachedThreadPool();
        // 此时两个线程会并发执行
        executorService.execute(new demoLifoOff());
        executorService.shutdown(); // 当在中间添加此之后只有第一个线程执行了，第二个由于关闭的线程池，而无法执行
        executorService.execute(new demoLifoOff());

    }
}
